package com.mazaiting.instructions.control;

import com.mazaiting.instructions.base.BranchInstruction;
import com.mazaiting.instructions.base.BytecodeReader;
import com.mazaiting.rtda.MtFrame;

/**
 * 的switch-case语句有两种实现方式：如果case值可以编码成一个索引表，则实现成tableswitch指令；
 * 否则实现成lookupswitch指令
 * <p>
 * int chooseFar(int i) {
 * switch (i) {
 * case -100: return -1;
 * case 0: return 0;
 * case 100: return 1;
 * default: return -1;
 * }
 * }
 *
 * @author mazaiting
 * @since 2021/8/15
 */
public class LookupSwitchInstruction {

    public static class LookupSwitch extends BranchInstruction {
        /**
         * 默认情况下执行跳转所需的字节码偏移量
         */
        private int defaultOffset;
        /**
         * case 对数
         */
        private int nPairs;
        /**
         * matchOffsets有点像Map，它的key是case值，value是跳转偏移量
         */
        private int[] matchOffsets;

        @Override
        public void fetchOperands(BytecodeReader reader) {
            reader.skipPadding();
            this.defaultOffset = reader.readU4();
            this.nPairs = reader.readU4();
            this.matchOffsets = reader.readU4s(nPairs * 2);
        }

        @Override
        public void execute(MtFrame frame) {
            // 键
            int key = frame.getOperandStack().popInt();
            for (int i = 0; i < nPairs * 2; i += 2) {
                if (matchOffsets[i] == key) {
                    int offset = matchOffsets[i + 1];
                    branch(frame, offset);
                    return;
                }
            }
            branch(frame, defaultOffset);
        }
    }
}
